<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Licensed ( https://opensource.org/licenses/MIT )
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// +----------------------------------------------------------------------
// | 快捷功能
// +----------------------------------------------------------------------
if (!function_exists("viewAssign")) {
    /**
     * 将数据赋值到模板变量
     * @param string $name
     * @param mixed $value
     */
    function viewAssign(string $name, mixed $value): void {
        $data = \Inphp\Core\Context::get("viewData", []);
        $data = is_array($data) ? $data : [];
        $data[$name] = $value;
        \Inphp\Core\Context::set("viewData", $data);
    }

    /**
     * 获取模板赋值
     * @return array
     */
    function getViewAssignData(): array {
        $data = \Inphp\Core\Context::get("viewData", []);
        return is_array($data) ? $data : [];
    }
}

if (!function_exists("assetsUrl")) {
    /**
     * 生成资源文件地址
     * @param string $url
     * @param string|null $moduleName
     * @param string $name
     * @return string
     */
    function assetsUrl(string $url, ?string $moduleName = null, string $name = "assets"): string {
        if (stripos($url, "http://") === 0 || stripos($url, "https://") === 0) {
            return $url;
        }
        if (stripos($url, "assets://") === 0) {
            $string = substr($url, 9);
            $path = explode("/", $string);
            $moduleName = $path[0];
            $url = join("/", array_slice($path, 1));
            return assetsUrl($url, $moduleName);
        }
        if (!empty($moduleName) && $name == "assets") {
            if (!defined("DEV_MODE")) {
                define("DEV_MODE", false);
            }
            //优先使用模块内资源
            $src = str_replace("//", "/", $url);
            $src = stripos($src, "/") === 0 ? substr($src, 1) : $src;
            //去除参数
            $src = stripos($src, "?") > 0 ? substr($src, 0, stripos($src, "?")) : $src;
            //先检测软链
            $assetsDir = \Inphp\Core\Config::get("define.assets");
            if (is_file($assetsDir."/modules/{$moduleName}/{$src}")) {
                return assetsUrl("/modules/{$moduleName}/{$src}");
            }
            $suffix = strtolower(strrchr($src, "."));
            if (empty($suffix)) {
                return assetsUrl($url);
            }
            $md5 = "/cache/".md5($moduleName.'/'.$url).$suffix;
            $attachmentDir = \Inphp\Core\Config::get("define.attachment");
            if (is_file($attachmentDir.$md5) && !DEV_MODE) {
                //重定向
                return attachmentUrl($md5);
            }
            $suffix = substr($suffix, 1);
            //仅允许的文件后缀
            $accessTypes = [
                "jpg"       => \Inphp\Core\Services\Http\Response::CONTENT_TYPE_IMAGE_JPEG,
                "jpeg"      => \Inphp\Core\Services\Http\Response::CONTENT_TYPE_IMAGE_JPEG,
                "png"       => \Inphp\Core\Services\Http\Response::CONTENT_TYPE_IMAGE_PNG,
                "gif"       => \Inphp\Core\Services\Http\Response::CONTENT_TYPE_IMAGE_GIF,
                "bmp"       => "image/bmp",
                "js"        => "application/javascript",
                "css"       => "text/css",
                "svg"       => "image/svg+xml",
                "webp"      => "image/webp",
                "mp3"       => "audio/mpeg"
            ];
            $assetsAccess = \Inphp\Core\Config::get("define.assetsAccess");
            $assetsAccess = is_array($assetsAccess) ? $assetsAccess : (is_string($assetsAccess) && !empty($assetsAccess) ? (@json_decode($assetsAccess, true) ?? []) : []);
            $accessTypes = !empty($assetsAccess) ? array_merge($accessTypes, $assetsAccess) : $accessTypes;
            if (!in_array($suffix, array_keys($accessTypes))) {
                return assetsUrl($url);
            }
            //文件不存在，则启用缓存模式
            $module = \Inphp\Core\Modules::getModule($moduleName);
            if ($module && (is_file($module->root."/assets/{$src}") || is_file($module->root."/{$src}"))) {
                //找到文件
                $content = file_get_contents($module->root.(is_file($module->root."/assets/{$src}") ? "/assets/{$src}" : "/{$src}"));
                //写入缓存
                if (!is_dir($attachmentDir."/cache")) {
                    @\Inphp\Core\Util\File::makeDir($attachmentDir."/cache");
                }
                if(file_put_contents($attachmentDir.$md5, $content) !== false) {
                    return attachmentUrl($md5).(DEV_MODE ? ("?".time()) : "");
                }
            }
            return assetsUrl($url);
        }
        $prefix = \Inphp\Core\Config::get("domain.{$name}");
        $prefix = strrchr($prefix, "/") === "/" ? substr($prefix, 0, -1) : $prefix;
        return $prefix.str_replace("//", "/", "/".$url);
    }
    //添加Smarty模板方法
    \Inphp\Core\Helper\SmartyPlugin::registerFunction("assets", function (array $params = []) {
        return assetsUrl($params["url"], $params["module"] ?? null);
    });
}
if (!function_exists("staticUrl")) {
    /**
     * 生成系统外的资源文件地址
     * @param string $url
     * @param string|null $module
     * @return string
     */
    function staticUrl(string $url, ?string $module = null): string {
        return assetsUrl($url, $module, "static");
    }
    //添加Smarty模板方法
    \Inphp\Core\Helper\SmartyPlugin::registerFunction("static", function (array $params = []) {
        return staticUrl($params["url"], $params["module"] ?? null);
    });
}
if (!function_exists("attachmentUrl")) {
    /**
     * 生成附件文件地址
     * @param string|null $url
     * @return string|null
     */
    function attachmentUrl(?string $url): ?string {
        $url = !empty($url) ? assetsUrl($url, null, "attachment") : null;
        if (!empty($url) && stripos($url, "http") !== 0) {
            $url = getHost().$url;
        }
        return $url;
    }
    //添加Smarty模板方法
    \Inphp\Core\Helper\SmartyPlugin::registerFunction("attachment", function (array $params = []) {
        return attachmentUrl($params["url"]);
    });
}
if (!function_exists('attachmentsUrl')) {
    /**
     * 多个文件地址
     * @param string|array|null $urls
     * @param string $split
     * @return array
     */
    function attachmentsUrl(null|string|array $urls, string $split = ","): array {
        if (empty($urls)) {
            return [];
        }
        $urls = is_array($urls) ? $urls : explode($split, $urls);
        $result = [];
        foreach ($urls as $url) {
            if ($src = attachmentUrl($url)) {
                $result[] = $src;
            }
        }
        return $result;
    }
}
if (!function_exists("url")) {
    /**
     * 转化链接
     * @param string $path
     * @param string|null $module
     * @return string
     */
    function url(string $path, ?string $module = null): string {
        if (stripos($path, "http") === 0) {
            return $path;
        }
        return \Inphp\Core\Modules::matchUri($path, $module);
    }
    //添加Smarty模板方法
    \Inphp\Core\Helper\SmartyPlugin::registerFunction("url", function (array $params = []) {
        return url($params["url"], $params["module"] ?? null);
    });
}

/**
 * 处理HTML，方便保存到数据库
 * @param null|string $html
 * @return string
 */
function encodeHtml(?string $html = null): string {
    if (empty($html)) {
        return "";
    }
    $attachmentUrl = \Inphp\Core\Config::get("domain.attachment");
    $html = str_replace("src=\"{$attachmentUrl}/", "src=\"/", $html);
    if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()){
        $html = stripslashes($html);
    }
    return htmlspecialchars($html, ENT_QUOTES);
}

/**
 * html解码
 * @param null|string $html
 * @return string
 */
function decodeHtml(?string $html = null): string {
    if (empty($html)) {
        return "";
    }
    $html = htmlspecialchars_decode($html, ENT_QUOTES);
    $attachmentUrl = \Inphp\Core\Config::get("domain.attachment");
    return str_replace("src=\"/", "src=\"{$attachmentUrl}/", $html);
}
//添加Smarty模板方法
\Inphp\Core\Helper\SmartyPlugin::registerModifier("htmlDecode", function (string $html) {
    return decodeHtml($html);
});

/**
 * 处理上传文件的路径
 * @param null|string|array $files
 * @return string|array|null
 */
function parseUploadFilesUrl(null|string|array $files): string|array|null {
    if (empty($files)) {
        return null;
    }
    $files = is_array($files) ? $files : explode(",", $files);
    $attachmentUrl = \Inphp\Core\Config::get("domain.attachment");
    if (stripos($attachmentUrl, "http") !== 0) {
        $attachmentUrl = getHost().$attachmentUrl;
    }
    $attachmentDir = \Inphp\Core\Config::get("define.attachment");
    $urls = [];
    foreach ($files as $file) {
        if (stripos($file, $attachmentUrl) === 0) {
            $url = substr($file, strlen($attachmentUrl));
        } elseif (stripos($file, strrchr($attachmentDir, "/")) === 0) {
            $url = substr($file, strlen(strrchr($attachmentDir, "/")));
        } else {
            $url = $file;
        }
        $url = stripos($url, "http") !== 0 && stripos($url, "?") > 0 ? substr($url, 0, stripos($url, "?")) : $url;
        if((stripos($url, "http") !== 0 && is_file($attachmentDir.$url)) || stripos($url, "http") === 0){
            $urls[] = $url;
        }
    }
    return count($urls) > 1 ? $urls : (count($urls) === 1 ? $urls[0] : null);
}

/**
 * 获取GET参数
 * @param string $name
 * @param mixed $defaultValue
 * @return mixed
 */
function GET(string $name, mixed $defaultValue = null): mixed {
    $client = \Inphp\Core\Context::getClient();
    $values = $client->get;
    $values = is_array($values) ? $values : [];
    $values[$name] = $values[$name] ?? $defaultValue;
    $values[$name] = $values[$name] == 'null' ? null : $values[$name];
    return $values[$name];
}

/**
 * 从HEADER里获取数据
 * @param string $name
 * @param mixed|null $defaultValue
 * @return mixed
 */
function HEADERS(string $name, mixed $defaultValue = null): mixed {
    $client = \Inphp\Core\Context::getClient();
    $values = $client->header;
    $name = strtoupper($name);
    $name = str_replace(" ", "_", $name);
    $name = str_replace("-", "_", $name);
    $values = is_array($values) ? $values : [];
    $values[$name] = $values[$name] ?? $defaultValue;
    $values[$name] = $values[$name] == 'null' ? null : $values[$name];
    return $values[$name];
}

/**
 * 获取POST参数
 * @param string $name
 * @param mixed $defaultValue
 * @return mixed
 */
function POST(string $name, mixed $defaultValue = null): mixed {
    $client = \Inphp\Core\Context::getClient();
    $values = $client->post;
    $values = is_array($values) ? $values : [];
    $values[$name] = $values[$name] ?? $defaultValue;
    $values[$name] = $values[$name] == 'null' ? null : $values[$name];
    return $values[$name];
}

/**
 * 获取POST参数
 * @param string $name
 * @param mixed $defaultValue
 * @return mixed
 */
function REQUEST(string $name, mixed $defaultValue = null): mixed {
    $client = \Inphp\Core\Context::getClient();
    $values = $client->request;
    $values = is_array($values) ? $values : [];
    $values[$name] = $values[$name] ?? $defaultValue;
    $values[$name] = $values[$name] == 'null' ? null : $values[$name];
    return $values[$name];
}

/**
 * 获取客户端IP
 * @return string
 */
function getIP(): string {
    $client = \Inphp\Core\Context::getClient();
    return $client->ip;
}

/**
 * 重定向
 * @param string $url
 * @param int $code
 */
function redirect(string $url, int $code = 302): void {
    $response = \Inphp\Core\Context::getResponse();
    $response->redirect($url, $code);
}

/**
 * 返回一组数据，用于JSON响应
 * @param mixed $error
 * @param mixed $message
 * @param mixed $data
 * @return array
 */
function message(mixed $error = 0, mixed $message = null, mixed $data = null): array {
    $data = is_array($error) || is_object($error) ? $error : (is_array($message) || is_object($message) ? $message : $data);
    $message = is_string($error) ? $error : (is_array($message) || is_object($message) ? null : $message);
    $error = is_array($error) || is_object($error) ? 0 : (is_string($error) ? 1 : $error);
    if ($error !== 0 && empty($message)) {
        $message = \Inphp\Core\Util\Error::get($error);
    }
    $message = is_string($message) ? $message : "success";
    $json = [
        "error" => $error,
        "message" => $message
    ];
    if(!is_null($data)){
        $json['data'] = $data;
    }
    return $json;
}

/**
 * HTTP Message 对象
 * @param mixed $error
 * @param mixed $message
 * @param mixed $data
 * @return \Inphp\Core\Object\Message
 */
function httpMessage(mixed $error = 0, mixed $message = null, mixed $data = null): \Inphp\Core\Object\Message {
    return new \Inphp\Core\Object\Message(message($error, $message, $data));
}

/**
 * websocket Message 对象
 * @param string $event
 * @param int $error
 * @param string $message
 * @param mixed $data
 * @return \Inphp\Core\Object\Message
 */
function websocketMessage(string $event, int $error = 0, ?string $message = null, mixed $data = null): \Inphp\Core\Object\Message {
    $json = message($error, $message, $data);
    $json['event'] = $event;
    return new \Inphp\Core\Object\Message($json);
}

/**
 * 快速响应数据，方便直接结束响应
 * @param mixed $body
 * @param string $contentType
 * @return \Inphp\Core\Services\Http\Response
 */
function httpResponse(mixed $body = null, string $contentType = \Inphp\Core\Services\Http\Response::CONTENT_TYPE_JSON): \Inphp\Core\Services\Http\Response {
    $response = \Inphp\Core\Context::getResponse();
    if (!is_null($body)) {
        $response->withBody($body, $contentType);
    }
    return $response;
}

/**
 * 获取Response对象
 * @return \Inphp\Core\Services\Http\Response
 */
function getHttpResponse(): \Inphp\Core\Services\Http\Response {
    return httpResponse();
}

/**
 * 获取客户端对象
 * @return null|\Inphp\Core\Object\Client
 */
function getClient(): ?\Inphp\Core\Object\Client {
    return \Inphp\Core\Context::getClient();
}

/**
 * 获取业务配置
 * @param string $map
 * @param string $name
 * @return mixed
 */
function getConfig(string $map, string $name = "public"): mixed {
    $map = \Inphp\Core\Util\Str::trim($map);
    $map = str_replace("/", ".", $map);
    return \Inphp\Core\Config::get("{$name}.{$map}");
}

/**
 * 获取域名地址，带HTTP
 * @param bool $scheme
 * @return string
 */
function getHost(bool $scheme = true): string {
    $client = getClient();
    $host = \Inphp\Core\Config::get("domain.main");
    $host = !empty($host) ? $host : ($client ? $client->host : "");
    $host = stripos($host, "http") === 0 ? $host : (($client && $client->https ? "https://" : "http://").$host);
    $host = strrchr($host, "/") === "/" ? substr($host, 0, -1) : $host;
    if (!$scheme) {
        $host = \Inphp\Core\Util\Str::deletePrefix($host, ["http://", "https://"]);
    }
    return $host;
}

/**
 * 生成URL地址参数串
 * @param array $params
 * @param bool $encode
 * @return string
 */
function makeUrlQuery(array $params, bool $encode = true): string {
    $string = [];
    foreach ($params as $key => $val) {
        $string[] = "{$key}=".($encode ? urlencode($val) : $val);
    }
    return join("&", $string);
}